﻿//////////////////////////////////////////////////////////////////////////////
//
//  Copyright © 1998-2024 Glodon Company Limited.  All rights reserved.
//
//  Use of this software is subject to the terms of the Glodon license
//  agreement provided at the time of installation or download, or which
//  otherwise accompanies this software in either electronic or hard copy form.  
//
//////////////////////////////////////////////////////////////////////////////

// Reviewed

#pragma once
#include "GcmpGeometryInterface.h"
#include "DiscretizeData.h"
#include "GcmpApiDeclaration.h"
#include "DiscreteEpsilonType.h"

namespace gcmp
{
    class ICurve2d;
    class ICurve3d;
    class IEdge;
    class IFace;
    class ISurface;
    class IBody;
    class IPolyCurve;
    class IPolyCurve3d;

    /// \brief 几何元素离散类，用于实现几何元素的离散
    ///
    class GCMP_GEOMETRY_INTERFACE_EXPORT AlgorithmDiscretize
    {
    public:
        /// \brief 设置是否使用Delaunay(狄洛尼)三角剖分算法，默认为false
        /// \param isUseDelaunay  是否使用Delaunay算法
        /// \return
        /// \note 开启后不保证一直离散要求，即重合的两个圆面，离散出来的顶点不一定重合；
        ///       对复杂的面（多个洞或边很多）性能会提升很多 
        static void SetIsUseDelaunayTriangulation(bool isUseDelaunay);

        /// \brief  把二维曲线离散成二维点集
        /// \param  pCurve2d                     二维曲线
        /// \param  dDistanceEpsilon             距离精度
        /// \param  dAngleEpsilon                角度精度
        /// \param  discretePoints               二维点集
        /// \return 成功返回true，失败返回false
       static bool Discretize(const ICurve2d* pCurve2d, double dDistanceEpsilon, double dAngleEpsilon, std::vector<Vector2d> &discretePoints);

        
        /// \brief  把三维曲线离散成点集
        /// \param pCurve3d                三维曲线
        /// \param dDistanceEpsilon        距离精度
        /// \param dAngleEpsilon           角度精度
        /// \param discretePoints          点集
        /// \return 成功返回true，失败返回false
        static bool Discretize(const ICurve3d* pCurve3d, double dDistanceEpsilon, double dAngleEpsilon, std::vector<Vector3d> &discretePoints);

        
        /// \brief  把拓扑边离散成点集
        /// \param pEdge                        拓扑边
        /// \param dDistanceEpsilon             距离精度
        /// \param dAngleEpsilon                角度精度
        /// \param discretePoints               点集
        /// \return bool 成功返回true，失败返回false
        static bool Discretize(const IEdge* pEdge, double dDistanceEpsilon, double dAngleEpsilon, std::vector<Vector3d> &discretePoints);


        /// \brief  将拓扑面离散成三角面片(不带索引)
        /// \param  pFace                         拓扑面
        /// \param dDistanceEpsilon               距离精度
        /// \param dAngleEpsilon                  角度精度
        /// \param dZValue                        水平拓扑面的 Z 坐标
        /// \param points                         点集，三个点构成一个三角片
        /// \param normals                        点集对应的法向
        /// \param pParameterUVs                  离散点在原来曲面上的参数,当输入为 nullptr 时不输出
        /// \return 成功返回true，失败返回false
        static bool Discretize(const IFace* pFace, double dDistanceEpsilon, double dAngleEpsilon, const double dZValue, std::vector<Vector3d> &points,
            std::vector<Vector3d> &normals, std::vector<Vector2d>* pParameterUVs);


        /// \brief  将拓扑面离散成三角面片(带索引)
        /// \param  pFace                    拓扑面
        /// \param  dDistanceEpsilon         距离精度
        /// \param  dAngleEpsilon            角度精度
        /// \param  dZValue                  水平拓扑面的 Z 坐标（标高）
        /// \param  vertexPoints             离散成的点集
        /// \param  normals                  点集对应的法向
        /// \param  triangleIndexs           顶点索引，每三个 vertexPoints 点一组作为三角片
        /// \param  pLineIndexs              顶点索引，每两个 vertexPoints 点作为线段，当输入为 nullptr 时不输出折线段
        /// \param  pParameterUVs            离散点在原来曲面上的参数,当输入为 nullptr 时不输出
        /// \return 成功返回true，失败返回false
        static bool Discretize(const IFace* pFace, double dDistanceEpsilon, double dAngleEpsilon, const double dZValue, std::vector<Vector3d> &vertexPoints,
            std::vector<Vector3d> &normals, std::vector<int> &triangleIndexs, std::vector<int>* pLineIndexs, std::vector<Vector2d>* pParameterUVs);


        /// \brief  把曲面离散成索引形式的三角面片(带索引)
        /// \param  pSurface                          曲面
        /// \param  dDistanceEpsilon                  距离精度
        /// \param  dAngleEpsilon                     角度精度
        /// \param  points                            离散成的点集
        /// \param  normals                           点集对应的法向
        /// \param  triangleIndexs                    三角面片链表（存三个顶点的索引）
        /// \param  pParameterUVs                     离散点在原来曲面上的参数,当输入为 nullptr 时不输出
        /// \return bool 成功返回true，失败返回false
        static bool Discretize(const ISurface *pSurface, double dDistanceEpsilon, double dAngleEpsilon, std::vector<Vector3d> &points,
            std::vector<Vector3d> &normals, std::vector<int> &triangleIndexs, std::vector<Vector2d>* pParameterUVs);


        /// \brief  把体离散成索引形式的三角面片(带索引)
        /// \param  pBody                                   体
        /// \param  dDistanceEpsilon                        距离精度
        /// \param  dAngleEpsilon                           角度精度
        /// \param  points                                  离散成的点集
        /// \param  normals                                 在原来曲面上的法向
        /// \param  triangleIndexs                          三角面片链表（存三个顶点在points中的索引，每三个索引构成一个三角形）
        /// \param  pParameterUVs                           离散点在原来曲面上的参数,当输入为 nullptr 时不输出
        /// \param  pEdgePoints                             离散边的点集
        /// \param  pEdgeIndexs                             离散边的点索引(两个顶点在edgePoints中的索引，构成一个线段)
        /// \param  pFaceToTriangleNum                      每个面对应离散后的三角面片数，面的顺序与体中面的顺序一致
        /// \param  pEdgeToLineNum                          每条边对应离散后的线段数，边的顺序与体中边的顺序一致
        /// \param  deType                                  几何离散的容差给定方式
        /// \return bool 成功返回true，失败返回false
        static bool Discretize(
            const IBody *pBody,
            double dDistanceEpsilon,
            double dAngleEpsilon,
            std::vector<Vector3d> &points,
            std::vector<Vector3d> &normals,
            std::vector<int> &triangleIndexs,
            std::vector<Vector2d> *pParameterUVs,
            std::vector<Vector3d> *pEdgePoints,
            std::vector<int> *pEdgeIndexs,
            std::vector<int> *pFaceToTriangleNum = nullptr,
            std::vector<int> *pEdgeToLineNum = nullptr,
            DiscreteEpsilonType deType = DiscreteEpsilonType::User);

        /// \brief  把体离散成索引形式的三角面片(带索引)    和Discretize不同的是，此版本的points  normals  pParameterUVs size相同, points可能有重复
        /// \param  pBody                                   体
        /// \param  dDistanceEpsilon                        距离精度
        /// \param  dAngleEpsilon                           角度精度
        /// \param  points                                  离散成的点集
        /// \param  normals                                 在原来曲面上的法向
        /// \param  triangleIndexs                          三角面片链表（存三个顶点在points中的索引，每三个索引构成一个三角形）
        /// \param  pParameterUVs                           离散点在原来曲面上的参数,当输入为 nullptr 时不输出
        /// \param  pEdgePoints                             离散边的点集
        /// \param  pEdgeIndexs                             离散边的点索引(两个顶点在edgePoints中的索引，构成一个线段)
        /// \param  pFaceToTriangleNum                      每个面对应离散后的三角面片数，面的顺序与体中面的顺序一致
        /// \param  pEdgeToLineNum                          每条边对应离散后的线段数，边的顺序与体中边的顺序一致
        /// \param  deType                                  几何离散的容差给定方式
        /// \return bool 成功返回true，失败返回false
        static bool DiscretizeWithIndices(
            const IBody *pBody,
            double dDistanceEpsilon,
            double dAngleEpsilon,
            std::vector<Vector3d> &points,
            std::vector<Vector3d> &normals,
            std::vector<int> &triangleIndexs,
            std::vector<Vector2d> *pParameterUVs,
            std::vector<Vector3d> *pEdgePoints,
            std::vector<int> *pEdgeIndexs,
            std::vector<int> *pFaceToTriangleNum = nullptr,
            std::vector<int> *pEdgeToLineNum = nullptr,
            DiscreteEpsilonType deType = DiscreteEpsilonType::User);

        /// \brief  把二维多段线离散成二维点集
        /// 
        /// \param  pGmIPolyCurve                二维多段线几何
        /// \param  dDistanceEpsilon             距离精度
        /// \param  dAngleEpsilon                角度精度
        /// \param  discretePoints               离散成的点集
        /// \return 成功返回true，失败返回false
        static bool Discretize(const IPolyCurve* pGmIPolyCurve, double dDistanceEpsilon, double dAngleEpsilon, std::vector<Vector2d> &discretePoints);

        /// \brief  把三维多段线离散成三维点集
        /// 
        /// \param  pGmIPolyCurve3d              三维多段线几何
        /// \param  dDistanceEpsilon             距离精度
        /// \param  dAngleEpsilon                角度精度
        /// \param  discretePoints               离散成的点集
        /// \return 成功返回true，失败返回false
        static bool Discretize(const IPolyCurve3d* pGmIPolyCurve3d, double dDistanceEpsilon, double dAngleEpsilon, std::vector<Vector3d>& discretePoints);
    
    };
}
